package edu.ntnu.superrss.service;

import edu.ntnu.superrss.models.SyndFeedImpl;
import edu.ntnu.superrss.models.User;
import edu.ntnu.superrss.utils.HibernateUtil;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.springframework.stereotype.Service;

/**
 *
 * @author Haakon Roekenes <hakondro at stud.ntnu.no>
 */
@Service
public class UserServiceImpl implements UserService {

    /**
     * Fetches the correct user from database based on a username String
     * <p>
     * This method fetch a User object from the database, based on a username
     * It uses uniqueResult of the Query interface since it expects a single result, an exception will be thrown
     * if more than one match is found
     *
     * @param  String a username String
     * @return User a complete user with all attributes
     * @throws  HibernateException
     */
    public User getUser(String username) throws HibernateException {
        Session session = HibernateUtil.getSessionFactory().openSession();
        Transaction tx = null;
        User user = null;
        try {
            tx = session.beginTransaction();
            
            user = (((User) session.createQuery("from User where username = ?)").setParameter(0, username).uniqueResult()));
            Hibernate.initialize(user);
            Hibernate.initialize(user.getEntriesRead());
            Hibernate.initialize(user.getEntriesThumbed());
//            Hibernate.initialize(user.getCategories());

            List<SyndFeedImpl> feeds = new ArrayList<SyndFeedImpl>(user.getFeeds());
            for (SyndFeedImpl feed : feeds) {
                Hibernate.initialize(feed.getCategories());
            }

            session.flush();
            tx.commit();
        } catch (RuntimeException e) {
            tx.rollback();
            throw e; // TODO: LOG4J
        } finally {
            session.close();
        }

        return user;
    }

    public User getUser(User user) {
        /**
         * Fetches the correct user from database based on a User object
         * <p>
         * This method fetch a User object from the database, based on a User object
         * It uses uniqueResult of the Query interface since it expects a single result, an exception will be thrown
         * if more than one match is found
         *
         * @param  User an incomplete User object containing username
         * @return User a complete user with all attributes
         * @throws  HibernateException
         */
        return getUser(user.getUsername());
    }

    public void updateUser(User user) throws HibernateException {
        Session session = HibernateUtil.getSessionFactory().openSession();
        Transaction tx = null;
        try {
            tx = session.beginTransaction();

            session.saveOrUpdate(user);
            
            session.flush();
            tx.commit();
        } catch (RuntimeException e) {
            tx.rollback();
            throw e; // TODO: LOG4J
        } finally {
            session.close();
        }
    }
}
